import asyncio
import json
from abc import ABC, abstractmethod
from typing import Final, Optional
from websockets.exceptions import ConnectionClosedOK

import websockets
from websockets.legacy.client import WebSocketClientProtocol


Address = tuple[str, int]


class MessengerClient(ABC):
    COMMAND_HEARTBEAT = "hb"

    def __init__(self ):
        self.websocket: Optional[WebSocketClientProtocol] = None
        self.queue: Optional[asyncio.Queue[str]] = None

    async def handle_command(self, data):
        pass

    async def receive(self):
        while True:
            try:
                data = await self.websocket.recv()
                if data is not None:
                    await self.handle_command(data)
            except ConnectionClosedOK as close_error:
              # 连接关闭
                print(f"--close_error:{close_error}")
                self.clear_message_queue()
                self.queue = None
                self.websocket = None
                raise Exception("连接关闭")


    async def keep_send(self):
        while True:
            item = await self.queue.get()
            await self._send_raw(item)
            self.queue.task_done()

    async def connect_server(self, address):
        if self.websocket is None:
            async with websockets.connect(address) as websocket:
                print(f"------连接成功-----")
                self.websocket = websocket
                # 连接成功回调
                self.queue = asyncio.Queue()

                await asyncio.gather(self.keep_send(),
                                     self.receive())


        else :
            if self.websocket.closed:
                self.clear_message_queue()
                self.queue = None
                self.websocket = None


    async def send_command(self, data:str):
        if self.queue is not None:
            await self.queue.put(data)

    async def _send_raw(self, data: str):
        assert self.websocket is not None
        await self.websocket.send(data)

    def clear_message_queue(self):
        for _ in range(self.queue.qsize()):
            self.queue.get_nowait()
            self.queue.task_done()


class AndroidMessengerClient(MessengerClient):
    def __init__(self , port ):
        super().__init__()
        self.port = port
        self.address = f"ws://192.168.110.252:{port}"
        self.callback = None


    async def handle_command(self, data):
        try:
            msg = json.loads(data)
            print(f"------msg:{msg}---")

        except Exception as e:
            pass

    async def keep_connection(self):
        while True:
            try:
                await self.connect_server(self.address)
            except Exception as e:
                pass
            await asyncio.sleep(3)


if __name__ == '__main__':
    client = AndroidMessengerClient(8888)
    asyncio.run(client.keep_connection())

